<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Layer Mask</title>
    <style>
        body {
            margin: 0;
        }

        h2,
        p {
            padding: 0 10px;
        }

        .main {
            height: 1000px;
            background: #f63;
            background: -webkit-linear-gradient(top, #f8f8f8, #f63);
            padding: 10px;
        }

        .btn-popup {
            padding: 0 10px;
            height: 40px;
            line-height: 40px;
            background: #f63;
            font-weight: 600;
            border: none;
            outline: none;
            color: #333;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            -webkit-tap-highlight-color: transparent;
        }

        code {
            background: #ddd;
            padding: 2px 5px;
            border-radius: 2px;
            color: #333;
            white-space: pre-wrap;
            display: inline-block;
            margin: 0 10px;
        }

        /****************** css for layer /*******************/

        .layer {
            position: fixed;
            overflow: auto;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: #666;
            background: rgba(0, 0, 0, 0.8);
            z-index: 100001;
            display: none;
            -webkit-will-change: background;
            will-change: background;
        }

        .layer-content {
            text-align: center;
            color: #333;
            font-size: 0.9em;
            padding: 0 5px;
            display: inline-block;
            width: 40%;
            max-width: 200px;
            height: 80px;
            line-height: 80px;
            background: #fff;
            position: absolute;
            top: 50%;
            left: 50%;
            -webkit-transform: translate(-50%, -50%);
            transform: translate(-50%, -50%);
            border-radius: 5px;
        }

        .layer-content>div {
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
        }

        .lock {
            overflow: hidden;
            touch-action: none;
        }

        .lock body {
            overflow: hidden;
            touch-action: none;
            margin-right: 17px;
        }

        .lock.mobile body {
            margin-right: 0;
        }
    </style>
</head>

<body>
    <h2>弹出层去除背景滚动--原生版</h2>
    <p>使用js构建的弹出层<b>类</b>，使用<code>new</code>的方式实例化，传入的参数为：</p>
    <code>{
    el: "触发元素，click触发弹出层",
    content: "弹出层内容",
    time: 0  // 显示持续时间
}</code>
    <p>使用 <b>passive</b> 事件和<code>overflow:hidden;</code>禁止滚动。<b>完美兼容PC和移动端。</b></p>
    <div class="main">
        <p>main content</p>
        <button class="btn-popup popup">Popup</button>
        <button class="btn-popup popup300">Popup 500</button>
    </div>
</body>
<script>
    function PopupLayer(options) {
        this.eles = [];
        this.times = [];
        this.contents = [];
        this.time = 0;
        this.animation = false;
        this.isMobile = navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i);
        if (this.isMobile) {
            document.querySelector("html").classList.add("mobile");
        }

        // init layer
        var html = '<div class="layer-content"><div class="content"></div></div>';
        this.layer = document.createElement('div');
        this.layer.className = "layer J_layer";
        this.layer.innerHTML = html;
        document.body.appendChild(this.layer);

        this.addElement = function (ele_options) {
            if (!ele_options.ele) {
                console.log("need ele option.");
                return;
            }
            // init trigger element
            document.querySelector(ele_options.ele).classList.add("J_popup");
            this.times.push(ele_options.time);
            this.eles.push(ele_options.ele);
            this.contents.push(ele_options.content);
        };

        this.forbidScroll = function (e) {
            e.preventDefault && e.preventDefault();
            e.returnValue = false;
            e.stopPropagation && e.stopPropagation();
            return false;
        }

        var me = this;

        this.toggleShow = function () {
            var now = +new Date();
            if (now < me.end_time) {
                me.animation = true;
                var op = (me.end_time - now) / me.trans_time;
                op = me.toggle ? (0.9 * (1 - op)) : (0.9 * op);
                me.layer.style.background = "rgba(0,0,0," + op + ")";
                console.log(op);
                window.requestAnimationFrame(me.toggleShow);
            } else {
                if (!me.toggle) {
                    me.layer.style.display = "none";
                    document.querySelector("html").classList.remove("lock");
                } else {
                    me.layer.style.background = "rgba(0,0,0,0.9)";
                }
                me.animation = false;
            }
        }

        this.showLayer = function () {
            me.layer.style.display = "block";
            me.trans_time = 200;
            me.end_time = +new Date() + me.trans_time;
            me.toggle = true;
            me.toggleShow();
            document.querySelector("html").classList.add("lock");
            window.addEventListener("mousewheel", me.forbidScroll);
            window.addEventListener("touchmove", me.forbidScroll, { passive: false });
        }

        this.hideLayer = function () {
            me.trans_time = 200;
            me.end_time = +new Date() + me.trans_time;
            me.toggle = false;
            me.toggleShow();
            window.removeEventListener("mousewheel", me.forbidScroll);
            window.removeEventListener("touchmove", me.forbidScroll, { passive: false });
        }

        document.addEventListener("click", function (e) {
            if (me.animation) {
                return;
            }
            var cl = e.target.classList;
            if (cl.contains("J_popup")) {
                // choose content
                var len = cl.length;
                while (len--) {
                    var index = me.eles.indexOf('.' + cl.item(len));
                    if (index > -1) {
                        document.querySelector(".layer-content .content").innerText = me.contents[index];
                        me.time = me.times[index];
                        break;
                    }
                }
                me.showLayer();
                if (me.time) {
                    setTimeout(function () {
                        me.hideLayer();
                    }, me.time + me.trans_time);
                }
            } else if (e.target.classList.contains("J_layer")) {
                me.hideLayer();
            }
        });
    }

    var layer = new PopupLayer();

    layer.addElement({
        ele: '.popup',
        content: 'content of layer'
    });
    layer.addElement({
        ele: '.popup300',
        content: 'content of layer 300',
        time: 300
    })
</script>

</html>